#include "timer.h"
#include <chrono>
#include <ctime>
#include <mutex>
#include <random>
#include <sstream>
#include <iomanip>
#include <iostream>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>



#define CB_BY_GLOBAL_FUNC 0
#define INVALID_TIMER_ID    -1 // 无效的定时器id
static int g_iTimerID = -1; // 定时器ID信息，递增


/***************************************************************
 * 功能：获取系统当前运行毫秒值
 * 返回值：
 *      uint64_t：系统当前运行毫秒值
 * *************************************************************/
static uint64_t getSystemMsTime()
{
    uint64_t ui64MilliSecondsTp = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now().time_since_epoch()).count(); // 毫秒
    return ui64MilliSecondsTp;
}

#if CB_BY_GLOBAL_FUNC
/***************************************************************
 * 功能：定时器线程
 * 输入参数：
 *      pUser：调用者
 *      iId：定时器的id
 * *************************************************************/
static void pfnTimerThreadTodo(void* pUser, int iId)
{
    Timer* pTimer = static_cast<Timer *>(pUser);
    if (pTimer)
    {
        pTimer->onTimeEvent(iId);
    }

    return;
}
#endif
/***************************************************************
 * 功能：构造函数
 * *************************************************************/
Timer::Timer()
    : m_bRunning(false)
    , m_iId(INVALID_TIMER_ID)
    , m_spth4TimerTask(nullptr)
{

}

/***************************************************************
 * 功能：析构函数
 * *************************************************************/
Timer::~Timer()
{
    if (INVALID_TIMER_ID != m_iId)
    {
        stopTimer(m_iId);
    }
}

/***************************************************************
 * 功能：开始定时器
 * 输入参数：
 *      stAttr：定时器属性
 * 返回值：
 *      int：定时器的id，停止定时器时会用到
 * *************************************************************/
int Timer::startTimer(const TimerAttributes& stAttr)
{
    if(m_bRunning)
    {
        printf(">>> [Timer::startTimer] timer id (%d) task thread is running, please stop first.\r\n", m_iId);
        return INVALID_TIMER_ID;
    }

    m_stAttr = stAttr;
    m_iId = ++g_iTimerID;
#if CB_BY_GLOBAL_FUNC
    m_spth4TimerTask = std::shared_ptr<std::thread>(new (std::nothrow) std::thread(pfnTimerThreadTodo, this, m_iId));
#else
    m_spth4TimerTask = std::shared_ptr<std::thread>(new (std::nothrow) std::thread(&Timer::onTimeEvent, this, m_iId));
#endif
    if (!(m_spth4TimerTask.get()))
    {
        m_iId = INVALID_TIMER_ID;
        m_bRunning = false;
        m_stAttr.bLoop = false;
        m_stAttr.iIntervalMs = 0;
        m_stAttr.pfn = nullptr;
        printf(">>> [Timer::startTimer] start timer task error, new thread failed.\r\n");
        return m_iId;
    }

    return m_iId;
}

/***************************************************************
 * 功能：停止定时器
 * 输入参数：
 *      id：定时器的id
 * *************************************************************/
void Timer::stopTimer(int iId)
{
    //printf("stoptimer iId (%d).\r\n", iId);
    if (iId == m_iId)
    {
        //if (m_bRunning)
        {
            m_bRunning = false;
            m_stAttr.bLoop = false;

            if (m_spth4TimerTask.get() && m_spth4TimerTask->joinable())
            {
                m_spth4TimerTask->join();
            }

            m_stAttr.iIntervalMs = 0;
            m_stAttr.pfn = nullptr;
            m_iId = INVALID_TIMER_ID;
        }
    }
    else
    {
        printf(">>> [Timer::startTimer] iId (%d) != m_iId (%d).\r\n", iId, m_iId);
    }

    return;
}

/***************************************************************
 * 功能：获取定时器的id
 * 返回值：
 *      int：定时器的id
 * *************************************************************/
int Timer::getTimerID()
{
    return m_iId;
}

/***************************************************************
 * 功能：响应处理具体的定时任务
 * 输入参数：
 *      iId：定时器的id
 * *************************************************************/
void Timer::onTimeEvent(int iId)
{
    if (iId == m_iId)
    {
        m_bRunning = true;

        if (m_stAttr.iIntervalMs < 0)
        {
            printf(">>> [Timer::startTimer] timer interval (%d)(ms) is < 0(ms).\r\n", m_stAttr.iIntervalMs);
            m_bRunning = false;
            return;
        }

        // 保证至少能够执行一次
        uint64_t start = 0, current = 0;
        int interval = 0; // 间隔时间
        start = getSystemMsTime(); // 开始计时

        do
        {
            current = getSystemMsTime(); // 当前计时
            interval = static_cast<int>(current - start);
            if (interval >= m_stAttr.iIntervalMs)
            {
                start = getSystemMsTime(); // 更新计时
                if (m_stAttr.pfn)
                {
                    m_stAttr.pfn();
                }
            }
            else
            {
                std::this_thread::yield();
                //std::this_thread::sleep_for(std::chrono::milliseconds(2)); // 让出cpu时间
            }

        } while (m_stAttr.bLoop && m_bRunning);

        //printf("exit timer thread m_iId (%d).\r\n", m_iId);

        m_bRunning = false;
        m_iId = INVALID_TIMER_ID;
    }
    else
    {
        m_bRunning = false;
        printf(">>> [Timer::startTimer] iId (%d) != m_iId (%d).\r\n", iId, m_iId);
    }

    return;
}


